﻿body = document.body;
view = document.getElementById("view");
workspace = document.getElementById("workspace");
codespace = document.getElementById("codespace");

width = 400;
height = 400;

view.style.width = width + "px";
view.style.height = height + "px";
view.style.left = window.innerWidth * 0.5 - view.offsetWidth * 0.5 + "px";
view.style.top = window.innerHeight * 0.5 - view.offsetHeight * 0.5 + "px";

init();

function init() {
	var exe = document.getElementById("execute");
	var run = document.getElementById("run");
	var hid = document.getElementById("hide");
	var sav = document.getElementById("save");
	
	execute.onclick = function() {
		runScript();
	}
	
	run.onclick = function() {
		clear();
		runScript();
	}
	
	hid.onclick = function() {
		hide();
	}
	
	sav.onclick = function() {
		save();
	}
	
	var so = document.getElementById("so");
	so.style.width = "50px";
	source.style.opacity = so.value / 100;
	so.onchange = function(evt) {
		source.style.opacity = evt.target.value / 100;
	}
	
	source.style.width = "300px";
	source.style.height = "200px";
	if(window.localStorage['source'] != undefined) {
		source.value = window.localStorage['source'];
		show();
	}
	else {
		source.value = "c = circle(200, 200, 100);";
		//hide();
	}
}

function show() {
	workspace.style.visibility = "visible";
}

function hide() {
	workspace.style.visibility = "hidden";
}

function runScript() {
	if(codespace.childNodes.length > 0) {
		codespace.removeChild(codespace.childNodes[0]);
	}
	var script = document.createElement("script");
	script.type = "text/javascript";
	script.textContent = document.getElementById("source").value;
	codespace.appendChild(script);
}

svgns = "http://www.w3.org/2000/svg";
xlinkns = "http://www.w3.org/1999/xlink";
svg = document.createElementNS(svgns, "svg");
grid = document.createElementNS(svgns, "g");
grid.id = "grid";
vg = document.createElementNS(svgns, "g");
vg.id = "vg";
svg.appendChild(grid);
svg.appendChild(vg);
view.appendChild(svg);

makeGrid(40, 40);
cssText = "stroke:rgb(0, 0, 0); fill: none;";

pause = true;
frameCount = 0;

errNofArgs = "인자의 개수가 일치하지 않습니다"
errNaN = "숫자가 아닌 인자가 있습니다";
errNaF = "인자가 function이 아닙니다";

window.onresize = function(evt) {
	view.style.width = width + "px";
	view.style.height = height + "px";
	view.style.left = window.innerWidth * 0.5 - view.offsetWidth * 0.5 + "px";
	view.style.top = window.innerHeight * 0.5 - view.offsetHeight * 0.5 + "px";
}

function fullscreen()
{
    size(window.innerWidth, window.innerHeight);
}

function size(w, h)
{
	clearGrid();
    width = w;
    height = h;
    view.style.width = width + "px";
	view.style.height = height + "px";
	view.style.left = window.innerWidth * 0.5 - view.offsetWidth * 0.5 + "px";
	view.style.top = window.innerHeight * 0.5 - view.offsetHeight * 0.5 + "px"; 
}

function background(color) {
	view.style.background = color;
}

function Line(target, x0, y0, x1, y1) { 
    var el = document.createElementNS(svgns, "line");
    el.setAttribute("x1", x0);
    el.setAttribute("y1", y0);
    el.setAttribute("x2", x1);
    el.setAttribute("y2", y1);
    el.style.cssText = cssText;
    target.appendChild(el);
}

function line(x0, y0, x1, y1) { 
    
    if(arguments.length != 4) { 
        throw errNofArgs; 
        return;
    }
    
    for(var i in arguments) {
        if(isNaN(arguments[i])) {
            throw errNaN;
            return;
        }
    }

    var el = document.createElementNS(svgns, "line");
    el.setAttribute("x1", x0);
    el.setAttribute("y1", y0);
    el.setAttribute("x2", x1);
    el.setAttribute("y2", y1);
    el.style.cssText = cssText;
    vg.appendChild(el);
    
    return el;
}

function rect(x, y, width, height, rx, ry) { 
    
    for(var i in arguments) {
        if(isNaN(arguments[i])) {
            throw errNaN;
            return;
        }
    }

    var el = document.createElementNS(svgns, "rect");
    if(arguments.length >= 4) {
        el.setAttribute("x", x);
        el.setAttribute("y", y);
        el.setAttribute("width", width);
        el.setAttribute("height", height);
    }
    if(arguments.length == 6) {
        el.setAttribute("rx", rx);
        el.setAttribute("ry", ry);
    }
    el.style.cssText = cssText;
    vg.appendChild(el);
    
    return el;
}

function polygon(points) { 
    var el = document.createElementNS(svgns, "polygon");
	if(arguments.length == 1) {
		el.setAttribute("points", points);
	}
    el.style.cssText = cssText;
    vg.appendChild(el);
    
    return el;
}

function polyline(points) { 
    var el = document.createElementNS(svgns, "polyline");
	if(arguments.length == 1) {
		el.setAttribute("points", points);
	}
    el.style.cssText = cssText;
    vg.appendChild(el);
    
    return el;
}

function path(d) { 
    var el = document.createElementNS(svgns, "path");
    if(arguments.length == 1) {
		el.setAttribute("d", d);
	}
    el.style.cssText = cssText;
    vg.appendChild(el);
    
    return el;
}

function triangle(x0, y0, x1, y1, x2, y2) { 
    
    var el = polygon(x0 + " " + y0 + " " +
                     x1 + " " + y1 + " " +
                     x2 + " " + y2);
    
    return el;
}

function circle(x, y, r) { 
    
    if(arguments.length != 3) { 
        throw errNofArgs; 
        return;
    }
    
    for(var i in arguments) {
        if(isNaN(arguments[i])) {
            throw errNaN;
            return;
        }
    }
    
    var el = document.createElementNS(svgns, "circle");
    el.setAttribute("cx", x);
    el.setAttribute("cy", y);
    el.setAttribute("r", r);
    el.style.cssText = cssText;
    vg.appendChild(el);
    
    return el;
}

function ellipse(x, y, rx, ry) { 
    
    if(arguments.length != 4) { 
        throw errNofArgs; 
        return;
    }
    
    for(var i in arguments) {
        if(isNaN(arguments[i])) {
            throw errNaN;
            return;
        }
    }
    
    var el = document.createElementNS(svgns, "ellipse");
    el.setAttribute("cx", x);
    el.setAttribute("cy", y);
    el.setAttribute("rx", rx);
    el.setAttribute("ry", ry);
    el.style.cssText = cssText;
    vg.appendChild(el);
    
    return el;
}

function repeat(func, n) { 
    
    if(arguments.length != 2) { 
        throw errNofArgs; 
        return;
    }
    
    if(!isNaN(arguments[0])) {
            throw "첫번째 " + errNaF;
            return;
    }
    
    if(isNaN(arguments[1])) {
            throw "두번째 " + errNaF;
            return;
    }
        
    for(var i = 0; i < n; i++) {
        func();
    }
}

function group() {
    var el = document.createElementNS(svgns, "g");
    for(var i in arguments) {
        el.appendChild(arguments[i]);
    }
    vg.appendChild(el);
    
    return el;
}

function clear()
{
    var n = vg.childNodes.length;
    for(var i = 0; i < n; i++) {
        vg.removeChild(vg.childNodes[0]);
    }
}

function clearGrid()
{
    var n = grid.childNodes.length;
    for(var i = 0; i < n; i++) {
        grid.removeChild(grid.childNodes[0]);
    }
}

function undo()
{
    if(vg.childNodes.length > 0) {
        vg.removeChild(vg.childNodes[vg.childNodes.length - 1]);
    }
}

function makeGrid(nx, ny)
{
    clearGrid();
    cssText = "stroke:rgb(220, 220, 220); fill: none;";
    var sx = width / nx;
    var sy = height / ny;
    for(var y = 0; y < ny; y++) {
        Line(grid, 0, y * sy, width, y * sy);
    }
    
    for(var x = 0; x < nx; x++) {
        Line(grid, x * sx, 0, x * sx, height);
    }
    cssText = "stroke:rgb(0, 0, 0); fill: none;";
    grid.style.visibility = "visible";
}

function random(min, max) {
	
	if(arguments.length > 2) { 
		throw errNofArgs; 
		return;
	}
	
	for(var i in arguments) {
		if(isNaN(arguments[i])) {
			throw errNaN;
			return;
		}
	}
	
	if(arguments.length == 1) { 
		return Math.random() * min;
	}
	
	if(arguments.length == 2) { 
		return Math.random() * (max - min) + min;
	}
}

function loadImage(url, x, y, w, h) {
    var el = document.createElementNS(svgns, "image");
    el.setAttributeNS(xlinkns, "xlink:href", url);
    el.setAttribute("x", x);
    el.setAttribute("y", y);
    el.setAttribute("width", w);
    el.setAttribute("height", h);
    vg.appendChild(el);
    return el;
}

function text(content, x, y) {
    var el = document.createElementNS(svgns, "text");
    if(arguments.length == 3) { 
        el.setAttribute("x", x);
        el.setAttribute("y", y);
    }
    el.textContent = content;
    vg.appendChild(el);
    return el;
}

function create(name) {
    var el = document.createElementNS(svgns, name);
    
    if(arguments.length == 2) { 
        el.id = arguments[1];
    }
    
    return el;
}

SVGElement.prototype.attr = function(name, value) {
	if(arguments.length == 1) {
		return this.getAttribute(name);
	}
    this.setAttribute(name, value); 
}

SVGElement.prototype.transf = function(value) { 
    this.setAttribute("transform", value); 
}

function translate(x, y) {
    return "translate(" + x + "," + y + ")";
}

function scale(sx, sy) {
    return "scale(" + sx + "," + sy + ")";
}

function rotate(angle) {
    return "rotate(" + angle + ")";
}

function clamp(x, min, max) {
    if(x < min) x = min;
    if(x > max) x = max;
    return x;
}

function dist(x0, y0, x1, y1) {
	var dx = x0 - x1;
	var dy = y0 - y1;
	return Math.sqrt(dx*dx + dy*dy);
	return Math.sqrt(dx*dx + dy*dy);
}

function rgb(r, g, b) {
    return "rgb(" + Math.floor(clamp(r, 0, 255)) + "," + 
                    Math.floor(clamp(g, 0, 255)) + "," +
                    Math.floor(clamp(b, 0, 255)) + ")";                 
}

function rgba(r, g, b, a) {
    return "rgba(" + Math.floor(clamp(r, 0, 255)) + "," + 
                     Math.floor(clamp(g, 0, 255)) + "," +
                     Math.floor(clamp(b, 0, 255)) + "," +
                     clamp(a, 0, 1) + ")";                  
}

function hsl(h, s, l) {
    return "hsl(" + h + "," + 
                    clamp(s, 0, 100) + "%," +
                    clamp(l, 0, 100) + "%)";                    
}

function hsla(h, s, l, a) {
    return "hsla(" + h + "," + 
                    clamp(s, 0, 100) + "%," +
                    clamp(l, 0, 100) + "%," +
                    clamp(a, 0, 1) + ")";                   
}

function play() {
    pause = false;
}

function stop() {
    pause = true;
}

function loop() {
}

function loopDelegate() {
    if(pause) return;
    loop();
    frameCount++;
}

function checkTab(evt) {
	var tab = "    ";
    var t = evt.target;
    var ss = t.selectionStart;
    var se = t.selectionEnd;
    // Tab key - insert tab expansion
    if (evt.keyCode == 9) {
        evt.preventDefault();
                
        // Special case of multi line selection
        if (ss != se && t.value.slice(ss,se).indexOf("\n") != -1) {
            // In case selection was not of entire lines (e.g. selection begins in the middle of a line)
            // we ought to tab at the beginning as well as at the start of every following line.
            var pre = t.value.slice(0,ss);
            var sel = t.value.slice(ss,se).replace(/\n/g,"\n"+tab);
            var post = t.value.slice(se,t.value.length);
            t.value = pre.concat(tab).concat(sel).concat(post);
                    
            t.selectionStart = ss + tab.length;
            t.selectionEnd = se + tab.length;
        }
                
        // "Normal" case (no selection or selection on one line only)
        else {
            t.value = t.value.slice(0,ss).concat(tab).concat(t.value.slice(ss,t.value.length));
            if (ss == se) {
                t.selectionStart = t.selectionEnd = ss + tab.length;
            }
            else {
                t.selectionStart = ss + tab.length;
                t.selectionEnd = se + tab.length;
            }
        }
    }
}

source.onkeydown = function(evt) {
	checkTab(evt);
}

function save(){
	window.localStorage['source'] = source.value;
	window.localStorage['timestamp'] = (new Date()).getTime();
}

timer = setInterval(loopDelegate, 1000 / 30);